<template>
  <el-button ref="buttonRef" type="primary" :icon="Plus"
             circle size="large" :style="style" style="font-size: 1.8rem;"
             @mousedown="startDrag" @touchstart="startDrag"/>
</template>

<script setup lang="ts">
import { computed, defineEmits, onMounted, reactive, ref } from 'vue'
import { Plus } from '@element-plus/icons-vue'

const buttonRef = ref()

const buttonPos = reactive({
  x: 0,
  y: 0,
  width: 0,
  height: 0
})

const startPos = reactive({
  x: 0,
  y: 0
})

const offsetPos = reactive({
  x: 0,
  y: 0
})

/**
 * 最小拖到阈值
 */
const dragThreshold = 5

const emit = defineEmits(['click'])

/**
 * 实时更新位置
 */
const style = computed(() => ({
  position: 'absolute',
  left: `${buttonPos.x}px`,
  top: `${buttonPos.y}px`,
  touchAction: 'none'
}))

onMounted(() => {
  initButtonPosition()
})

const initButtonPosition = () => {
  buttonPos.x = window.innerWidth - 50
  buttonPos.y = window.innerHeight - 120
  buttonPos.width = buttonRef.value.$el.offsetWidth
  buttonPos.height = buttonRef.value.$el.offsetHeight
}

const startDrag = (event) => {
  event.preventDefault()

  const touch = event.touches ? event.touches[0] : event

  startPos.x = touch.clientX
  startPos.y = touch.clientY

  offsetPos.x = touch.clientX - buttonPos.x
  offsetPos.y = touch.clientY - buttonPos.y

  document.addEventListener('mousemove', onDrag)
  document.addEventListener('mouseup', stopDrag)
  document.addEventListener('touchmove', onDrag, { passive: false })
  document.addEventListener('touchend', stopDrag)
}

const onDrag = (event) => {
  const touch = event.touches ? event.touches[0] : event

  // 计算新位置，并限制在边界内
  const newX = touch.clientX - offsetPos.x
  const newY = touch.clientY - offsetPos.y

  buttonPos.x = Math.max(0, Math.min(newX, window.innerWidth - buttonPos.width))
  buttonPos.y = Math.max(40, Math.min(newY, window.innerHeight - buttonPos.height - 70))
}

const stopDrag = (event) => {
  document.removeEventListener('mousemove', onDrag)
  document.removeEventListener('mouseup', stopDrag)
  document.removeEventListener('touchmove', onDrag)
  document.removeEventListener('touchend', stopDrag)

  const touch = event.changedTouches ? event.changedTouches[0] : event
  const deltaX = Math.abs(touch.clientX - startPos.x)
  const deltaY = Math.abs(touch.clientY - startPos.y)

  // 此时为点击
  if (deltaX <= dragThreshold && deltaY <= dragThreshold) {
    emit('click', event)
  }
}
</script>
